﻿using System;
using System.Collections.Generic;
using System.Text;

namespace TT.Runtime
{
    //VM基本设计
    //0.执行栈，记录每一层函数调用，单独分配一个区域保存
    //1.临时栈，因为寄存器vm并不能直接使用，vm使用内存模拟，所以opcode 不使用寄存器设计，直接使用临时变量操作
    //称为temp ,临时栈，大部分操作改在临时栈上执行
    //2.寄存器，因主要运算直接在临时栈进行，此处只需记录一些关键信息，比如返回值 规定reg0 为返回值

    //五个内存区域
    //const 常量
    //arg   入参区
    //temp  临时区
    //reg0  返回值区 
    //heap

    //LoadConst const->temp
    //LoadArg   arg->temp
    //Move      temp->temp

    //尽量减少指令族
    //指令族压缩到4bit可以表示
    public enum OPCode : byte //指令族
    {
        /// <summary>
        /// 基本流指令
        /// </summary>
        OP_NOP = 0,//空指令 
        OP_LoadConst = 1,//加载常量 到 变量 ，可以有各种load扩展
        OP_LoadArg = 2,//加载参数到变量
                       //OP_Temp,// 临时变量声明指令？用不着，这个信息可以放在函数中

        //Temp ID 和 Temp Addr
        OP_Move = 3,//在变量 和寄存器 之间复制 //可以 不允许太大 //move target 包括 temp addr ， return addr，heap addr，万能的move，，包括fill
        //所有的memcopy方法都用move完成
        //OP_Block,//块定义
        //OP_JmpUnsafe,//关闭jmpsafe检查？是否要做成指令型的，指令性就意味着要改bytecode
        //OP_Block_Loop,//块c重进？
        //OP_Block_Break,//块跳出
        //这两个只存在逻辑上，实际上只要有块定义，然后让Jmp只允许Jmp到Block开始与结束位置就可以做安全检查了
        //保留块定义和安全检查就可以防止瞎jmp，移除块定义和安全检查，则可以加强保密性
        OP_Math = 4,//加减乘除一站通 op1 type ;//针对什么数据类型的 op2 什么操作符 +-*/  op其它，只允许寄存器操作

        OP_Conv = 5,//原型类型转换bool 当uint8处理， 数学计算不用管int16和 int8的，check变成参数
        //OP_Conv_check,//int32 转 int16时会检查范围有没有超出，int32 转uint32同理，如果超范围了，报错
        //OP_MathLogic,//逻辑判断一站通,逻辑运算也合并进Math指令
        //OOP的 类型转换也交给Conv指令
        
        OP_Jmp = 6,//goto
        //没有BR类代码？会造成执行复杂度提高？最终执行 block_loop 和 block_break 不如goto
        OP_IfJmp = 7,//条件跳转

        OP_Ret = 8,//结束 

        OP_Call = 9,//调用函数指令  函数id， 参数offset（in temp），参数size //包含oop call

        //上面的指令可以搞基本流了
        //OOP的多态也交给Call


        /// <summary>
        /// OOP相关指令
        /// </summary>
        //OOP_HeapBox =10,//分配一个Box，他的大小不由boxtype本身决定，而是根据box里面的东西决定
        //            //可以用box 装值类型，或者装数组，不允许对象数组（设计容器去，数组必须是值数组，用int32[] 来装对象（里面是对象地址））
        //            //内置 List 来解决
        OP_HeapAlloc = 10,//分配一个堆上对象，返回一个堆地址,,heap box 和 heap alloc 合并
                          //构造函数直接用call 调用
        OP_HeapFree = 11,//free一个堆上的对象，可能调用析构函数
                         //析构函数用free引发
        OP_HeapAddRef = 12,//引用一个对象

        //OOP_GetHeapAddr=13,//从栈上得到堆地址,this指针在栈上时用 也可以通过Conv搞定
        OP_ErrorHandle = 13,//错误处理家族
        // try catch throw 等等
        //OOP_GetType = 15,//得到一个对象的Typeid 可以用
        //OOP_Type = 16,//判断一个对象是否是另一个对象，或继承，或实现 都使用Conv包括

        OP_Debug = 15,//直接触发调试断点
        //可以考虑把这个用调试指令的方式加入
        //OP_Debug_DefineBlock
        //OP_Debug_OpenJmpSafeCheck,//
        OP_Try,
        OP_Leave,//go final .try块结束 或 catch块结束
        OP_Final,//滚回leave点
        OP_Throw


    }
    /// <summary>
    /// 加载类的扩展指令
    /// </summary>
    //    OP_Ext_Load = 0x0100,
    //    OP_Ext_LoadConst_0_1Byte,
    //    OP_Ext_LoadConst_0_2Byte,
    //    OP_Ext_LoadConst_0_3Byte,
    //    OP_Ext_LoadConst_0_4Byte,
    //    OP_Ext_LoadConst_0_5Byte,
    //    OP_Ext_LoadConst_0_6Byte,
    //    OP_Ext_LoadConst_0_7Byte,
    //    OP_Ext_LoadConst_0_8Byte,
    //    OP_Ext_LoadConst_1_1Byte,
    //    OP_Ext_LoadConst_1_2Byte,
    //    OP_Ext_LoadConst_1_3Byte,
    //    OP_Ext_LoadConst_1_4Byte,
    //    OP_Ext_LoadConst_1_5Byte,
    //    OP_Ext_LoadConst_1_6Byte,
    //    OP_Ext_LoadConst_1_7Byte,
    //    OP_Ext_LoadConst_1_8Byte,
    //    OP_Ext_LoadConst_m1_1Byte,
    //    OP_Ext_LoadConst_m1_2Byte,
    //    OP_Ext_LoadConst_m1_3Byte,
    //    OP_Ext_LoadConst_m1_4Byte,
    //    OP_Ext_LoadConst_m1_5Byte,
    //    OP_Ext_LoadConst_m1_6Byte,
    //    OP_Ext_LoadConst_m1_7Byte,
    //    OP_Ext_LoadConst_m1_8Byte,
    //    OP_Ext_LoadConst_float32_1,
    //    OP_Ext_LoadConst_float64_1,

    //    OP_Ext_LoadConst2Reg0,                     //const->reg0
    //    OP_Ext_LoadArg2Reg0,                       //arg->reg0
    //    /// <summary>
    //    /// Call 扩展指令
    //    /// </summary>
    //    OP_Ext_Call = 0x0200,
    //    OP_Ext_TailCall,//尾递归调用，先出栈，再call
    //    OP_Ext_CallSub,//调用子函数，一种优化思路，不推参数，共用寄存器栈
    //    OP_Ext_ReturnSub,//退出子函数

    //    /// <summary>
    //    /// //这些都是jmp扩展指令,不需要一开始就实现扩展指令
    //    /// </summary>
    //    OP_Ext_Jmp = 0x0300,
    //    OP_Ext_EQJmp,//== jmp
    //    OP_Ext_NEQJmp,//!= jmp
    //    OP_Ext_GTJmp,//> jmp
    //    OP_Ext_GTEJmp,//>= jmp
    //    OP_Ext_LTJmp,//<= jmp
    //    OP_Ext_LTEJmp,//<= jmp
}
